package com.personal.core.xml;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XMLWriter
{
    private Writer writer;

    public XMLWriter(boolean bShowVersion) throws IOException
    {
        this.writer = new BufferedWriter(new OutputStreamWriter(System.out));

        if (!bShowVersion)
        {
            return;
        }
        this.writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    }

    public XMLWriter(Writer writer) throws IOException
    {
        this.writer = writer;
        this.writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
    }

    public XMLWriter(Writer writer, boolean bShowVersion) throws IOException
    {
        this.writer = writer;

        if (!bShowVersion)
        {
            return;
        }

        this.writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    }

    /**
     * @param node node
     * @throws Exception Exception
     */
    public void writeNode(Node node) throws Exception
    {
        if (this.writer == null)
        {
            return;
        }

        writeNotFomat(node);
    }

    private void writeNotFomat(Node node) throws Exception
    {
        if (this.writer == null)
        {
            return;
        }

        if (node.getNodeType() == 1)
        {
            this.writer.write("<");
            this.writer.write(node.getNodeName());

            NamedNodeMap map = node.getAttributes();
            if (map != null)
            {
                for (int i = 0; i < map.getLength(); ++i)
                {
                    if (map.item(i).getNodeType() == 2)
                    {
                        this.writer.write(" ");
                        this.writer.write(map.item(i).getNodeName());
                        this.writer.write("=\"");
                        this.writer.write(map.item(i).getNodeValue());
                        this.writer.write("\"");
                    }
                }
            }
            this.writer.write(">");
        }

        NodeList childs = node.getChildNodes();

        for (int i = 0; i < childs.getLength(); ++i)
        {
            if (childs.item(i).getNodeType() == 1)
            {
                writeNotFomat(childs.item(i));
            }
            else
            {
                if (childs.item(i).getNodeType() != 3)
                {
                    continue;
                }
                if (!childs.item(i).getTextContent().equals(""))
                {
                    this.writer.write(replaceSpecialChar(childs.item(i).getTextContent()));
                }
            }
        }

        writeNotFomatEnd(node);
    }

    private void writeNotFomatEnd(Node node) throws IOException
    {
        if (node.getNodeType() != 1)
        {
            return;
        }

        this.writer.write("</");
        this.writer.write(node.getNodeName());
        this.writer.write(">");
    }

    private String replaceSpecialChar(String textContent)
    {
        return textContent.replace("<", "&lt;").replace(">", "&gt;").replace("'", "&apos;").replace("\"", "&quot;");
    }

    /**
     * @throws IOException IOException
     */
    public void flush() throws IOException
    {
        this.writer.flush();
    }
}